package com.woniu.server.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.woniu.client.DepotClient;
import com.woniu.client.OrderClient;
import com.woniu.client.PermissionsClient;
import com.woniu.client.PointsmallClient;
import com.woniu.dto.*;
import com.woniu.exception.RebornException;
import com.woniu.form.AddAccountForm;
import com.woniu.form.AddAccountRoleForm;
import com.woniu.form.AddUserAccountForm;
import com.woniu.mapper.TUserMapper;
import com.woniu.model.Result;
import com.woniu.model.TUser;
import com.woniu.model.UserLoginLog;
import com.woniu.params.*;
import com.woniu.server.TUserService;
import com.woniu.server.UserLoginLogService;
import com.woniu.utils.JwtUtil;

import com.woniu.utils.execption.useraccount.UserAccountException;
import com.woniu.utils.execption.useraccount.UserAccountExceptionCode;
import com.woniu.utils.utils.*;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 吴彦祖
 * @since 2024年05月23日
 */
@Service
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TUser> implements TUserService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private TUserMapper tUserMapper;

    @Resource
    private RedissonClient redissonClient;
    @Resource
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private PointsmallClient pointsmallClient;
    @Autowired
    private PermissionsClient permissionsClient;
    @Resource
    private UserLoginLogService userLoginLogService;

    @Resource
    private OrderClient orderClient;

    @Resource
    private DepotClient depotClient;
    /**
     * 该方法用于返回一个 token
     * @param user 传入一个Tuser类型 的对象
     * @return
     */
    private String token(TUser user){
        //根据账号id查询得到角色 存入redis中
        String roleName = permissionsClient.selectRoleByAccountId(String.valueOf(user.getAccountId())).getData().getRoleName();
        HashMap<String, Object> accessBody = new HashMap<>();

        String random = new Snowflake(1, 1).nextIdStr();
        accessBody.put("random",random);
        //生成不重复的随机数 返回给前端 30分钟过期
        String accessToken = JwtUtil.createUserToken("token", accessBody);

        //已返回给前端的token作为key,存入带敏感数据的token到redis
        Map<String, Object> map = BeanUtil.beanToMap(user);
        map.put("role",roleName);
        String refreshToken = JwtUtil.createToken(map,24*3600,JwtUtil.userSecret);
        redisUtil.set(accessToken,refreshToken,24*3600);//redis的过期时间为1天
        //HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        HttpServletResponse resp = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
        resp.setHeader("token",accessToken);
        resp.setHeader("Access-Control-Expose-Headers","token");
        return accessToken;
    }

    /**
     * 密码登录
     * @param param 登录所需的账号和密码
     * @return
     */
    @Override
    public TUser pwdLogin(UserLoginParam param) throws Exception {
        System.out.println(param.getUsername());
        TUser user = tUserMapper.selectOne(new QueryWrapper<TUser>().eq("username", param.getUsername()));
        //TUser user = this.getOne(new QueryWrapper<TUser>().eq("username", param.getUsername()));
        if (user==null) throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_NOT_REGISTER);
        String md5 = MD5Util.md5(param.getPassword(),param.getUsername());
        if (!md5.equals(user.getPassword())) {
            throw new Exception("密码错误");
        }
        if (user.getState()!=StateData.ACCOUNT_STATE_NORMAL) throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_STATE_ERROR);
        //将accessToken 返回给前端
        token(user);
        //记录用户登录日志
        UserLoginLog userLoginLog = new UserLoginLog();
        userLoginLog.setUserId(user.getId());
        userLoginLog.setPhone(user.getPhone());
        userLoginLog.setLoginTime(LocalDateTime.now());
        userLoginLogService.save(userLoginLog);
        return user;
    }

    /**
     * 发送注册验证码
     * @param mobile 用户手机号
     * @throws Exception
     */
    @Override
    public void sendRegisterCode(String mobile) throws Exception {
        //每次在发验证码 之前 判断 RedisKeyUtil.registerCodeOnMinute(mobile) 这个健是否存在
        //等于是 在这里做的判断 存在建 就不能发 不存在就可以发
        if (redisUtil.exist(RedisKeyUtil.registerCodeOnMinute(mobile))) {
            throw new Exception("1分钟内不能发送多条验证码");
        }
        //判断该手机号码发送验证码的次数是否>=5
        if (redisUtil.exist(RedisKeyUtil.sendMessageNumber(mobile))){
            String s = redisUtil.get(RedisKeyUtil.sendMessageNumber(mobile));
            int number = Integer.parseInt(s);
            if (number>=5){
                throw new Exception("1小时内发送短信的次数不能大于5次");
            }
        }

        Result<AccountDto> accountDtoResult =  permissionsClient.byPhone(mobile);
        if (accountDtoResult.getCode()!=200) {
            throw new Exception("调用异常");
        }
        if (accountDtoResult.getData()!=null) {
            throw new Exception("该手机号已存在");
        }
        //发送短信  https://106.ihuyi.com/webservice/sms.php?method=Submit
        //调用第三方的短信服务发送验证码
        //将手机号码存到消息队列中 让消息队列执行 发送验证码的功能
        rabbitTemplate.convertAndSend("register_phone_queue",mobile);
    }

    /**
     * 根据验证码注册 账号
     * @param param 注册所需的数据
     * @return
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public UserRegisterDto registerByCode(CodeRegisterParam param) throws Exception {
        //注册要加锁
        RLock phoneLock = redissonClient.getFairLock(RedisKeyUtil.phoneLock(param.getPhone()));
        RLock userNameLock = redissonClient.getFairLock(RedisKeyUtil.userNameLock(param.getUsername()));
        //方式1 注意 调用方法的顺序 就是上锁的顺序
        //phoneLock.lock();
        //userNameLock.lock();

        //方式2 传参的顺序 就是上锁的顺序
        RLock lock = redissonClient.getMultiLock(phoneLock, userNameLock);
        TUser userInfo = null;
        if (lock.tryLock(10, TimeUnit.SECONDS)) {
            try {
                //判断用户验证码输入错误的总次数 >=5 下面的代码无法执行
                if (redisUtil.exist(RedisKeyUtil.codeErrorNumber(param.getPhone()))){
                    System.out.println(redisUtil.exist(RedisKeyUtil.codeErrorNumber(param.getPhone())));
                    if (Integer.parseInt(redisUtil.get(RedisKeyUtil.codeErrorNumber(param.getPhone())))>=5){
                        throw new Exception("验证码错误次数达到上限");
                    }
                }

                if (!(param.getCode().equals(redisUtil.get(RedisKeyUtil.sendRegisterCodeKey(param.getPhone()))))) {
                    //验证码输入错误的情况 允许错误5次
                    if (redisUtil.exist(RedisKeyUtil.codeErrorNumber(param.getPhone()))){
                        redisUtil.incr(RedisKeyUtil.codeErrorNumber(param.getPhone()));
                        if (Integer.parseInt(redisUtil.get(RedisKeyUtil.codeErrorNumber(param.getPhone())))>=5){
                            redisUtil.del(RedisKeyUtil.codeErrorNumber(param.getPhone()));
                        }
                    }else {
                        redisUtil.set(RedisKeyUtil.codeErrorNumber(param.getPhone()),"1",5*60);

                    }
                    throw new Exception("验证码有误");
                }
                QueryWrapper<TUser> wrapper = new QueryWrapper<>();
                wrapper.eq("phone",param.getPhone());
                userInfo = tUserMapper.selectOne(wrapper);

                if (userInfo!=null){
                    throw new Exception("手机号已注册");
                }
                //调用权限模块 的账号 用户名,手机号 不能重复
                Result<List<AccountDto>> accountDtoResult = permissionsClient.byPhoneOrUsername(param.getPhone(),param.getUsername());
                if (accountDtoResult.getCode()!=200) {
                    throw new Exception("调用异常");
                }
                if (accountDtoResult.getData()!=null&&accountDtoResult.getData().size()>0) {
                    throw new Exception("该手机号或用户名已存在");
                }

                userInfo = BeanUtil.toBean(param, TUser.class);
                userInfo.setPassword(MD5Util.md5(userInfo.getPassword(),userInfo.getUsername()));
                userInfo.setState(StateData.USER_DEFAULT_ACCOUNTSTATE);
                userInfo.setEnrollTime(LocalDateTime.now().toString());
                userInfo.setCredibility(StateData.USER_DEFAULT_CREDIBILITY);
                userInfo.setRealNameState(param.getIdentityCard()==null||param.getIdentityCard().equals("")?StateData.USER_NOT_REAL_NAME:StateData.USER_YES_REAL_NAME);
                userInfo.setScore(StateData.USER_DEFAULT_SOCRE);
                userInfo.setPublicizeCode(new Snowflake(1,1).nextIdStr());
                if(param.getOtherPublicizeCode()!=null&&!param.getOtherPublicizeCode().equals("")){
                    TUser tUser = getOne(new QueryWrapper<TUser>().eq("publicize_code", param.getOtherPublicizeCode()));

                    if (tUser==null) {
                        throw new Exception("该推广码不存在");
                    }
                    userInfo.setPublicizeId(tUser.getId());
                    userInfo.setOtherPublicizeCode(tUser.getPublicizeCode());
                    tUser.setCredibility(tUser.getCredibility()+10);
                    updateById(tUser);
                }else {
                    userInfo.setOtherPublicizeCode(null);
                }
                userInfo.setPublicizeId(StateData.USER_DEFAULT_PUBLICIZEID);
                userInfo.setState(StateData.USER_DEFAULT_ACCOUNTSTATE);
                userInfo.setAvatarPath(StateData.USER_DEFAULT_AVATAR);
                //向权限模块的账号表添加数据
                AddUserAccountForm form = new AddUserAccountForm();
                form.setAccountPhone(userInfo.getPhone());
                form.setAccountPass(userInfo.getPassword());
                form.setAccountName(userInfo.getUsername());
                form.setAccountNickname(userInfo.getNickName());
                Result<AccountDto> result =  permissionsClient.addUserAccount(form);
                //权限模块添加角色数据--------------
                AddAccountRoleForm form1 = new AddAccountRoleForm();
                form1.setRoleId(1L);
                form1.setAccountId(Long.valueOf(result.getData().getAccountId()));
                permissionsClient.addAccountRole(form1);

                userInfo.setAccountId(result.getData().getAccountId());
                tUserMapper.insert(userInfo);
                //完成注册后删除验证码
                redisUtil.del(RedisKeyUtil.sendRegisterCodeKey(param.getPhone()));
            }finally {
                lock.unlock();
            }

        }else {
            throw new Exception("服务器繁忙");
        }
        //返回给前端
        UserRegisterDto dto = BeanUtil.toBean(userInfo, UserRegisterDto.class);
        return dto;
    }

    /**
     * 验证码登录
     * @param param 验证码和手机号
     * @return
     */
    @Override
    public TUser codeLogin(CodeLoginParam param) {

        //判断用户验证码输入错误的总次数 >=5 下面的代码无法执行
        if (redisUtil.exist(RedisKeyUtil.codeErrorNumber(param.getPhone()))){
            System.out.println(redisUtil.exist(RedisKeyUtil.codeErrorNumber(param.getPhone())));
            if (Integer.parseInt(redisUtil.get(RedisKeyUtil.codeErrorNumber(param.getPhone())))>=5){
                throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_CODE_CEILING);
            }
        }

        if (!(param.getCode().equals(redisUtil.get(RedisKeyUtil.sendLoginCodeKey(param.getPhone()))))) {
            //验证码输入错误的情况 允许错误5次
            if (redisUtil.exist(RedisKeyUtil.codeErrorNumber(param.getPhone()))){
                redisUtil.incr(RedisKeyUtil.codeErrorNumber(param.getPhone()));
                if (Integer.parseInt(redisUtil.get(RedisKeyUtil.codeErrorNumber(param.getPhone())))>=5){
                    redisUtil.del(RedisKeyUtil.codeErrorNumber(param.getPhone()));
                }
            }else {
                redisUtil.set(RedisKeyUtil.codeErrorNumber(param.getPhone()),"1",5*60);

            }
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_CODE_ERROR);
        }


        //走到这里说明验证码输入是正确的 校验用户名 放行登录即可
        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",param.getPhone());
        TUser userInfo = tUserMapper.selectOne(wrapper);
        if (userInfo.getState()!=StateData.ACCOUNT_STATE_NORMAL) throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_STATE_ERROR);

        //记录登录日志
        UserLoginLog userLoginLog = new UserLoginLog();
        userLoginLog.setUserId(userInfo.getId());
        userLoginLog.setPhone(userInfo.getPhone());
        userLoginLog.setLoginTime(LocalDateTime.now());
        userLoginLogService.save(userLoginLog);

        return userInfo;
    }

    /**
     * 用户收藏商品
     * @param goodsId 商品id
     * @param userId  用户id
     */
    @Override
    public void collect(Integer goodsId, int userId) throws Exception {
        Result<GoodsDto> result = pointsmallClient.goodsById(goodsId);
        if (result.getCode()!=200) {
            throw new Exception("调用商品服务异常");
        }
        if (result.getData()==null){
            throw new Exception("商品不存在");
        }
        GoodsDto goodsDto = result.getData();
        if (goodsDto.getState()!= StateData.GOODS_STATE_NORMAL) throw new Exception("图书状态异常");
        //判断用户是否已经收藏过该商品
        if (redisUtil.zscore(RedisKeyUtil.collectList(userId),goodsId+"")!=null){
            throw new Exception("你已经收藏过该商品");
        }
        //redis 添加 用户的收藏信息
        redisUtil.zadd(RedisKeyUtil.collectList(userId),goodsId+"",new Date().getTime());
        //增加 该书籍的收藏数量
        redisUtil.zincrby(RedisKeyUtil.collectRank(),goodsId+"",1d);
    }

    @Override
    public void delCollect(Integer goodsId, int userId) throws Exception {

        Result<GoodsDto> result = pointsmallClient.goodsById(goodsId);
        if (result.getCode()!=200) {
            throw new Exception("调用商品服务异常");
        }
        if (result.getData()==null){
            throw new Exception("商品不存在");
        }
        //判断用户是否已收藏 图书
        //判断用户是否还未收藏 图书
        if (redisUtil.zscore(RedisKeyUtil.collectList(userId),goodsId+"")==null){
            throw new Exception("你还未收藏过该图书");
        }


        //redis 取消 用户的收藏信息
        redisUtil.zrem(RedisKeyUtil.collectList(userId),goodsId+"");
        //减少 该书籍的收藏数量
        redisUtil.zincrby(RedisKeyUtil.collectRank(),goodsId+"",-1d);
    }

    /**
     * 查看我的收藏
     * @param pageNum 第几页
     * @param pageSize 每页条数
     * @param userId 用户id
     * @return
     * @throws Exception
     */
    @Override
    public Page<GoodsDto> myCollect(Integer pageNum, Integer pageSize, int userId) throws Exception {

        pageNum = pageNum==null?1:pageNum;
        pageSize = pageSize==null?3:pageSize;
        Integer start = (pageNum-1)*pageSize;
        Integer end = pageNum*pageSize-1;
        Set<String> set = redisUtil.zrevrange(RedisKeyUtil.collectList(userId), start, end);
        if (set==null||set.size()==0) {
            throw new Exception("还未收藏商品");
        }
        Set<Integer> ids = set.stream().map(Integer::valueOf).collect(Collectors.toSet());
        //根据reids的用户收藏的商品id 查询商品数据
        Result<List<GoodsDto>> result = pointsmallClient.goodsByList(ids);
        if (result.getCode()!=200) {
            throw new Exception("调用商品服务异常");
        }
        if (result.getData()==null){
            throw new Exception("商品不存在");
        }

        if (result.getData().size()!=ids.size()) {
            throw new Exception("存在商品不存在");
        }

        long total = redisUtil.zcard(RedisKeyUtil.collectList(userId));
        long pages = total%pageSize==0?total/pageSize:total/pageSize+1;
        Page<GoodsDto> page = new Page<>();
        page.setPages(pages);
        page.setTotal(total);
        page.setCurrent(pageNum);
        page.setRecords(result.getData());
        page.setSize(pageSize);
        return page;
    }

    /**
     * 用户添加商品进入购物车
     * @param param
     */
    @Override
    public void addShopping(AddShoppingParam param) throws Exception {
        Result<GoodsDto> result = pointsmallClient.goodsById(param.getGoodsId());
        if (result.getCode()!=200) {
            throw new Exception("调用商品服务异常");
        }
        if (result.getData()==null){
            throw new Exception("商品不存在");
        }
        GoodsDto goodsDto = result.getData();
        if (goodsDto.getState()!= StateData.GOODS_STATE_NORMAL) {
            throw new Exception("商品状态异常");
        }
        if (goodsDto.getNumber() < param.getNumber()) {
            throw new Exception("库存不足");
        }
        if (redisUtil.zscore(RedisKeyUtil.userShopping(param.getUserId()),param.getGoodsId()+"")==null){

        //等于null 说明 首次添加 要添加两张表的数据 添加用户购物车列表的数据
        redisUtil.zadd(RedisKeyUtil.userShopping(param.getUserId()),param.getGoodsId()+"",new Date().getTime());
        try {
            //添加 该商品的详细信息 用户添加的数量等
            HashMap<String, Object> map = new HashMap<>();
            map.put("goodsId",goodsDto.getId()+"");
            map.put("name",goodsDto.getName()+"");
            map.put("price",goodsDto.getPrice().toString());
            map.put("img",goodsDto.getImg()+"");
            map.put("number",param.getNumber()+"");
            redisUtil.hmest(RedisKeyUtil.shoppingInfo(param.getUserId(),param.getGoodsId()),map);
        } catch (Exception e) {
            redisUtil.zrem(RedisKeyUtil.userShopping(param.getUserId()),param.getGoodsId()+"");
            throw e;
        }
        }else {
            //redisUtil.hset(RedisKeyUtil.shoppingInfo(param.getUserId(),param.getGoodsId()),"number",param.getNumber()+"");
            redisUtil.hincrby(RedisKeyUtil.shoppingInfo(param.getUserId(),param.getGoodsId()),"number",param.getNumber());

        }
    }

    /**
     * 删除购物车的商品信息
     * @param ids 商品id 集合
     * @param userId 用户id
     */
    @Override
    public void delShopping(List<Integer> ids, int userId) throws Exception {
        //用户传入的商品id 集合 判断是否传入重复的商品id
        Set<Integer> collect = ids.stream().collect(Collectors.toSet());

        if (collect.size()!=ids.size()) {
            throw new Exception("传入重复的商品id");
        }
        //查看redis 中与传入的商品id 是否匹配
        Set<String> set = redisUtil.zrange(RedisKeyUtil.collectList(userId));
        if (set.size()<ids.size()) {
            throw new Exception("存在没有收藏的商品");
        }

        Set<Integer> redisGoodsIds = set.stream().map(Integer::valueOf).collect(Collectors.toSet());

        // 判断redisGoodsIds是否包含collect的所有元素
        if (!redisGoodsIds.containsAll(collect)) {
            throw new Exception("传入的商品id中存在未收藏的商品");
        }
        //移除元素 图书排行榜收藏量减少1
        for (Integer goodsId : collect) {
            redisUtil.zrem(RedisKeyUtil.collectList(userId),goodsId+"");
            redisUtil.zincrby(RedisKeyUtil.collectRank(),goodsId+"",-1d);
        }


    }
    /**
     * 分页查询购物车 数据
     * @param pageNum 第几页
     * @param pageSize 每页几条数据
     * @param userId 用户id
     * @return
     * @throws Exception
     */
    @Override
    public Page<Map<Object, Object>> selAllShopping(Integer pageNum, Integer pageSize, int userId) {
        pageNum = pageNum==null?1:pageNum;
        pageSize = pageSize==null?3:pageSize;
        Integer start = (pageNum-1)*pageSize;
        Integer end = pageNum*pageSize-1;
        Set<String> set = redisUtil.zrevrange(RedisKeyUtil.userShopping(userId), start, end);
        ArrayList<Map<Object, Object>> list = new ArrayList<>();
        for (String s : set) {
            Integer bookId = Integer.parseInt(s);
            Map<Object, Object> map = redisUtil.hgetall(RedisKeyUtil.shoppingInfo(userId, bookId));
            list.add(map);
        }
        long total = redisUtil.zcard(RedisKeyUtil.userShopping(userId));
        long pages = total%pageSize==0?total/pageSize:total/pageSize+1;
        Page<Map<Object,Object>> page = new Page<>();
        page.setPages(pages);
        page.setTotal(total);
        page.setCurrent(pageNum);
        page.setRecords(list);
        page.setSize(pageSize);
        return page;
    }

    @Override
    public void modifyShopping(ModifyShoppingParam param) throws Exception {
        Result<GoodsDto> result = pointsmallClient.goodsById(param.getGoodsIds());
        if (result.getCode()!=200) {
            throw new Exception("调用商品服务异常");
        }
        if (result.getData()==null){
            throw new Exception("商品不存在");
        }

        if (redisUtil.zscore(RedisKeyUtil.userShopping(param.getUserId()),param.getGoodsIds()+"")==null){
            throw new Exception("你的购物车还未添加商品");
        }

        if (redisUtil.hgetall(RedisKeyUtil.shoppingInfo(param.getUserId(),param.getGoodsIds()))==null){
            throw new Exception("你的购物车没有该商品");
        }
        //拿到指定的购物详细信息
        Map<Object, Object> map = redisUtil.hgetall(RedisKeyUtil.shoppingInfo(param.getUserId(), param.getGoodsIds()));

        int bookId = Integer.parseInt(String.valueOf(map.get("bookId")));
        //int number = Integer.parseInt(String.valueOf(map.get("number")));
        //判断map 的number 数量 是否为0 为0 删除整个键值对 并 删除 用户的购物车列表 相关的该条数据
        if (param.getNumber()==0){
            redisUtil.delHest(RedisKeyUtil.shoppingInfo(param.getUserId(), param.getGoodsIds()));
            //删除 用户 购物车列表 信息
            redisUtil.zrem(RedisKeyUtil.userShopping(param.getUserId()),bookId+"");
        }else {
            //不是的情况让数量减一即可
            redisUtil.hset(RedisKeyUtil.shoppingInfo(param.getUserId(), param.getGoodsIds()),"number",param.getNumber()+"");
        }
    }

    /**
     * 实名认证
     * @param img 身份证图片
     * @param userId 用户id
     * @return
     * @throws Exception
     */
    @Override
    public TUser authentication(MultipartFile img, int userId) throws Exception {
        if (img.isEmpty()) {
            throw new Exception("上传的图片为空");
        }
        // 获取文件名
        String fileName = img.getOriginalFilename();
        // 创建文件对象，表示存储路径
        File dest = new File("D:\\Desk\\test\\card" + File.separator + fileName);
        TUser tUser = getById(userId);
        try {
            // 确保目录存在
            dest.getParentFile().mkdirs();
            // 保存文件到本地
            img.transferTo(dest);
            // 返回文件路径
            String filePath = dest.getAbsolutePath();
            Map<String, String> map = BaiduyunOCRUtil.idCord(filePath);
            //判断其他账号是否存在 该身份证号码
            TUser user = getOne(new QueryWrapper<TUser>().eq("identity_card", map.get("公民身份号码")));
            if (user!=null) throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_EXITS_CARDID);
            if (tUser==null) {
                throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_NOT_REGISTER);
            }
            if (tUser.getRealNameState().longValue()!=StateData.USER_NOT_AUTHENTICATION) throw new UserAccountException(UserAccountExceptionCode.USER_NOT_AUTHENTICATION);
            tUser.setRealNameState(StateData.USER_IS_AUTHENTICATION);
            tUser.setIdentityCard(map.get("公民身份号码"));
            tUser.setRealName(map.get("姓名"));
            updateById(tUser);

            //System.out.println("文件保存路径: " + filePath);
        } catch (Exception e) {
            //补偿机制
            if (dest.exists()) {
                boolean deleted = dest.delete();
                if (!deleted) {
                    System.err.println("无法删除文件: " + dest.getAbsolutePath());
                }
            }
            throw new RuntimeException(e);
        }
        return tUser;
    }

    /**
     * 用户修改头像
     * @param image 新头像数据
     * @return
     * @throws Exception
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public String modifyImg(MultipartFile image,int userId) throws Exception {
        TUser user = getById(userId);
        if (user==null) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_NOT_REGISTER);
        }
        if (!FileUtil.isImageFile(image.getInputStream())) {
            throw new Exception("文件类型异常");
        }
        String filePath = null;
        try {
            String oldName = image.getOriginalFilename();
            String suffix = oldName.substring(oldName.lastIndexOf("."));
            String fileName = UUID.randomUUID().toString();

            filePath = OSSUtil.uploadFile(image.getInputStream(),   fileName+suffix, "jinaisen");
            user.setAvatarPath(filePath);
            updateById(user);
        } catch (Exception e){
            if (filePath!=null)
                OSSUtil.deleteFile("jinaisen", cn.hutool.core.io.FileUtil.getName(filePath));
            throw new Exception("上传图片异常");
        }

        //删除从数据库取出的旧头像
        OSSUtil.deleteFile("jinaisen", cn.hutool.core.io.FileUtil.getName(user.getAvatarPath()));
        return filePath;
    }

    /**
     * 用户修改个人信息
     * @param param 要修改的个人信息数据
     * @return
     */
    @Override
    public TUser modifyMyInfo(ModifyMyInfoParam param) {
        TUser tUser = getById(param.getUserId());
        if (tUser==null) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_NOT_REGISTER);
        }
        tUser.setNickName(param.getNikeName());
        updateById(tUser);
        return tUser;
    }

    /**
     * 用户修改密码
     * @param param
     */
    @Override
    @GlobalTransactional(rollbackFor = Throwable.class)
    public void modifyPwd(ModifyPwdParam param) throws Exception {
        TUser tUser = getById(param.getUserId());
        if (tUser==null) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_NOT_REGISTER);
        }
        //数据库的密码
        String dbPwd = tUser.getPassword();
        //用户输入的旧密码
        String oldPassPwd = MD5Util.md5(param.getOldPassword(), tUser.getUsername());
        //用户输入的新密码
        String newPassPwd = MD5Util.md5(param.getNewPassword(), tUser.getUsername());
        //输入原密码有误
        if (!dbPwd.equals(oldPassPwd)) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_OLD_PASSWORD_NO_PASS);
        }
        //输入的新密码和原密码相同
        if (dbPwd.equals(newPassPwd)) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_PASSWORD_REPEAT);
        }
        tUser.setPassword(newPassPwd);
        //更新权限模块的密码
        Result<?> result = permissionsClient.modifyUserPass(tUser.getAccountId(),newPassPwd);
        if (result.getCode()!=200) {
            throw new Exception("调用其他服务异常");
        }
        updateById(tUser);
    }

    /**
     * 根据用户id　添加信誉分
     * @param param
     * @return
     */
    @Override
    public TUser addCredibility(AddCredibilityParam param) {
        TUser user = tUserMapper.selectOne(new QueryWrapper<TUser>().eq("account_id",param.getId()));
        if (user.getState()!= StateData.ACCOUNT_STATE_NORMAL) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_STATE_ERROR);
        }
        Long count =  user.getCredibility()+ param.getCredibility();
        if (count.longValue()>100) {
            count = 100L;
        }
        if (count.longValue()<0) {
            count = 0L;
        }

        user.setCredibility(count);
        updateById(user);
        return user;
    }

    /**
     * 上传头像
     * @param image  用户头像数据
     * @param userId 用户id
     * @return
     * @throws Exception
     */
    @Override
    public String uploadImg(MultipartFile image, int userId) throws Exception {
        TUser user = getById(userId);
        if (user==null) {
            throw new UserAccountException(UserAccountExceptionCode.ACCOUNT_NOT_REGISTER);
        }
        if (!FileUtil.isImageFile(image.getInputStream())) {
            throw new Exception("文件类型异常");
        }
        String filePath = null;
        try {
            String oldName = image.getOriginalFilename();
            String suffix = oldName.substring(oldName.lastIndexOf("."));
            String fileName = UUID.randomUUID().toString();

            filePath = OSSUtil.uploadFile(image.getInputStream(),   fileName+suffix, "jinaisen");
            user.setAvatarPath(filePath);
            updateById(user);
        } catch (Exception e){
            if (filePath!=null)
                OSSUtil.deleteFile("jinaisen", cn.hutool.core.io.FileUtil.getName(filePath));
            throw new Exception("上传图片异常");
        }

        return filePath;
    }

    /**
     * 用户查询我的订单
     * @return list用户自己的订单
     */
    @Override
    public List<OrderDto> checkMyOrder(int id) {
        Result<List<OrderDto>> result = orderClient.findMyOrders(id);
        if (result.getCode()!=200){
            throw  new RebornException(result.getMessage(),result.getCode());
        }
        List<OrderDto> data = result.getData();
        if (data==null||data.isEmpty()){
            throw new RebornException("您还没有任何订单哦",60001);
        }
        return data;
    }

    /**
     * 用户查询自己的订单详情
     * @return list用户自己的订单详情
     */
    @Override
    public List<OrderDetailsDto> checkMyOrderDetail(int id, String orderNum) {
        Result<List<OrderDetailsDto>> result = orderClient.selectAllOrderDetailByOrderId(orderNum);
        if (result.getCode()!=200){
            throw  new RebornException(result.getMessage(),result.getCode());
        }
        List<OrderDetailsDto> data = result.getData();
        if (data==null||data.isEmpty()){
            throw new RebornException("暂无订单详情,请先等待员工到达",60001);
        }
        return data;
    }

    /**
     * 用户查询所有垃圾类别
     * @return list垃圾类别
     */
    @Override
    public List<JunkTypeDto> checkJunkType() {
        Result<List<JunkTypeDto>> result =  depotClient.checkJunkType();
        if (result.getCode()!=200){
            throw new RebornException(result.getMessage(),result.getCode());
        }
        return result.getData();
    }


//    /**
//     * 用户查看垃圾类别
//     * @return list垃圾类别
//     */
//    @Override
//    public List<OrderDetailsDto> checkMyOrderDetail(int id, String orderNum) {
//        Result<List<OrderDetailsDto>> result = orderClient.selectAllOrderDetailByOrderId(orderNum);
//        if (result.getCode()!=200){
//            throw  new RebornException(result.getMessage(),result.getCode());
//        }
//        List<OrderDetailsDto> data = result.getData();
//        if (data==null||data.isEmpty()){
//            throw new RebornException("暂无订单详情,请先等待员工到达",60001);
//        }
//        return data;
//    }
}
